import {BASE_SOCKET_URL} from "./service";

export class Socket {

    constructor() {
        this.heartInterval = 1000 * 10;
        this.heartSeverTimeout = 1000 * 60;
        this.url = "";
        this.device = "Applets";
        this.subscriptions = {}
    }

    initWebSocket() {
        this.url = BASE_SOCKET_URL + this.device + "?token=" + uni.getStorageSync("token");
        const _this = this;
        _this.websocket = uni.connectSocket({
            url: this.url,
            success(res) {
                return res;
            },
            fail() {
                console.log('正在尝试重新连接。。。。')
            }
        })
        // 连接错误

        uni.onSocketError(function (res) {
            console.log('WebSocket连接打开失败，请检查！');
            _this.setErrorMessage()
        });


        // 收到消息的回调
        uni.onSocketMessage(function (res) {
            _this.setOnmessageMessage(res)
            _this.reset()
        });

// 连接成功
        uni.onSocketOpen(function (res) {
            console.log('WebSocket连接已打开！');
            //清空订阅
            for(var key in _this.subscriptions){
                _this.stompSubscribe(key,_this.subscriptions[key]);
            }
            _this.start()
        });

        uni.onSocketClose(function (res) {
            console.log('WebSocket 已关闭！');
        });

    }

    reconnect() {
        // 重新连接
        if (this.lockReconnect) return;
        this.lockReconnect = true;
        //没连接上会一直重连，设置延迟避免请求过多
        this.timeoutnum && clearTimeout(this.timeoutnum);
        this.timeoutnum = setTimeout(() => {
            //新连接
            this.initWebSocket();
            this.lockReconnect = false;
            // console.log("subscriptions",this.subscriptions)
        }, 5000);

    }


    reset() { // 重置心跳
        // 清除时间
        clearTimeout(this.heartTimeObj);
        clearTimeout(this.serverTimeoutObj);
        // 重启心跳
        this.start();
    }

    start() { // 开启心跳
        const _this = this;
        this.heartTimeObj && clearTimeout(this.heartTimeObj);
        this.serverTimeoutObj && clearTimeout(this.serverTimeoutObj);
        this.heartTimeObj = setTimeout(() => {
            // 这里发送一个心跳，后端收到后，返回一个心跳消息，
            // console.log("this.websocket", _this.websocket)
            console.log("start" + '   状态码：' + this.websocket.readyState)
            if (this.websocket && this.websocket.readyState == 1) { // 如果连接正常
                this.websocketsend('mt');
            } else { // 否则重连
                this.reconnect();
            }
            this.serverTimeoutObj = setTimeout(() => {
                //超时关闭
                // console.log("超时关闭")
                // this.websocket.close();
            }, this.heartSeverTimeout);

        }, this.heartInterval)
    }

    setOnmessageMessage(event) {
        const _this = this
        _this.reset();
        let message = event.data;
        // console.log(event)
        if ("mt" === message) return;
        if ("connected" == message) {
            console.log("实时消息连接成功")
            return;
        }
        let headerStr = message.substring(0, message.indexOf("\n\n"))
        let command = headerStr.substring(0, headerStr.indexOf("\n"));
        headerStr = message.substring(message.indexOf("\n") + 1,message.indexOf("\n\n"))
        let bodyJson = message.substring(message.indexOf("\n\n") + 2, message.length-2)
        var lines = headerStr.split("\n");
        let headers = {};
        lines.forEach((line) => {
            let keyValue = line.split(":");
            headers[keyValue[0]] = keyValue[1];
        })
        let body = bodyJson;
        try {
            body = JSON.parse(bodyJson)
        } catch (err) {
            console.log(err)
        }

        let destination = headers["destination"];

        if (command == "MESSAGE") {
            let messageCallback = _this.subscriptions[destination]
            if (messageCallback) {
                messageCallback(destination, body, headers)
            }
        } else if (command == "P2P") {
            let messageCallback = _this.subscriptions[destination]
            let fromUser = headers["fromUser"]
            if (messageCallback) {
                messageCallback(destination, body, headers, fromUser)
            }
        }

    }

    setErrorMessage() {
        //重连
        this.reconnect();
    }


    beforeDestroy() {
        //this.closeWebSocket();
    }

//websocket发送消息
    websocketsend(messsage) {
        // console.log(this.websocket)
        this.websocket.send({
            data: messsage
        })
    }

    closeWebSocket() { // 关闭websocket
        this.heartTimeObj && clearTimeout(this.heartTimeObj);
        this.serverTimeoutObj && clearTimeout(this.serverTimeoutObj);
        // console.log("即将取消订阅",this.subscriptions)
        //清空订阅
        for(var subscription in this.subscriptions){
            this.stompUnsubscribe(subscription);
        }
        this.subscriptions={}
        this.websocket.close();

    }



    createMessage(command, headers, body) {
        let message = command + "\n";
        if (headers) {
            for (let headerKey in headers) {
                message += headerKey + ":" + headers[headerKey] + "\n";
            }
        }
        message += "\n";
        if (body) {
            message += JSON.stringify(body) + "^@";
        }
        return message;
    }

    stompPublish(destination, body) {
        let headers = {destination: destination, "content-type": "application/json"};
        let message = this.createMessage("SEND", headers, body)
        this.websocketsend(message);
    }

    stompP2P(destination, toUser, body) {
        let headers = {destination: destination, toUser: toUser, "content-type": "application/json"};
        let message = this.createMessage("P2P", headers, body)
        this.websocketsend(message);
    }

    stompSubscribe(destination, messageCallback) {
        let headers = {destination: destination, "content-type": "application/json"};
        let message = this.createMessage("SUBSCRIBE", headers)
        this.websocketsend(message);
        this.subscriptions[destination] = messageCallback;
    }

    stompUnsubscribe(destination) {
        let headers = {destination: destination, "content-type": "application/json"};
        let message = this.createMessage("UNSUBSCRIBE", headers)
        this.websocketsend(message);
        // this.subscriptions[destination] = void 0;
        delete this.subscriptions[destination];
    }


}
